package cn.learn.office.excel_v3.write;

import cn.learn.office.excel_v3.ConvertFieldName;
import cn.learn.office.excel_v3.IGetter;
import cn.learn.office.excel_v3.write.sort.HandlerExcelColumnSort;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * excel导出数据的配置信息
 * 多表头跨列合并测试通过，跨行测试尚未处理
 * 跨行的 headerRowNum 设置没有计算，所以尚有问题
 *
 * @author huangyezhan
 * @version 3.1
 * @date 2021年05月21日16:48
 */
@Slf4j
@Getter
public class ExcelExportConfig {

    public ExcelExportConfig(Class<? extends HandlerExcelColumnSort> handlerSort,
                             ExcelType excelType,
                             String excelName,
                             String sheetName,
                             HeaderRow[] headerRow,
                             int[] width,
                             int columnNum,

                             WriteOrder[] writeOrderKeys,
                             List<?> content,
                             ExcelPosition[] positions) {

        this.handlerSort = handlerSort;
        this.excelType = excelType;
        this.excelName = excelName;
        this.sheetName = sheetName;
        this.headerRow = headerRow;
        this.width = width;
        this.columnNum = columnNum;
        this.writeOrderKeys = writeOrderKeys;
        this.content = content;
        this.positions = positions;

        this.headerRowNum = headerRow == null ? 0 : headerRow.length;
    }


    /**
     * 确定使用那种规则写入excel表格数据
     */
    private final Class<? extends HandlerExcelColumnSort> handlerSort;

    /**
     * 需要导出的Excel表格格式 .xls .xlsx
     * 默认 .xlsx
     */
    private final ExcelType excelType;
    /**
     * excel的表格名称
     */
    private final String    excelName;
    /**
     * sheet的名字
     */
    private final String    sheetName;

    /**
     * 表头
     */
    private final HeaderRow[] headerRow;

    /**
     * 每列的宽度
     * 自定义列宽，如果不用自定义，就会自适应，自适应，如果内容太长，会出现只看到一列的情况
     * 启动自定义,则把每一列的宽度都填写上
     * excel单元格的默认宽度8.11 自定义9*256=8.22，10*256=9.22，11*256=10.22
     */
    private final int[] width;

    /**
     * 列的数量
     */
    private final int columnNum;
    /**
     * 列头的行数
     */
    private final int headerRowNum;


    /**
     * 数据的填写内容顺序
     */
    private final WriteOrder[] writeOrderKeys;

    /**
     * 导入Excel表格的数据的集合
     */
    private final List<?> content;

    /**
     * 定义指定cell内容位置的数组,只能同时指定所有列的位置
     * 指定 left,right,center
     */
    private final ExcelPosition[] positions;


    @Getter
    @AllArgsConstructor
    public enum ExcelType {
        /**
         * excel的两种格式
         */
        XLS(".xls"),
        XLSX(".xlsx");

        private final String type;
    }

    /**
     * 数据的写入顺序
     */
    @Setter
    @Getter
    @NoArgsConstructor
    @Accessors(fluent = true)
    public static class WriteOrder {
        /**
         * 写入数据顺序的名称 key
         * map的key或者实体类的字段名
         */
        private String name;
        /**
         * String格式转换
         * https://www.cnblogs.com/Dhouse/p/7776780.html
         */
        private String format;

        /**
         * 值映射，例如状态码值映射
         */
        private Map<Object, Object> valueMapping;

        public void setName(IGetter<T> name) {
            this.name = ConvertFieldName.convertToFieldName(name);
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static ExportConfigBuilder builder() {
        return new ExportConfigBuilder();
    }

    @Setter
    @NoArgsConstructor
    @Accessors(fluent = true)
    public static class ExportConfigBuilder {
        private Class<? extends HandlerExcelColumnSort> handlerSort;

        private ExcelType excelType = ExcelType.XLSX;
        private String    excelName = "新建Excel表格";
        private String    sheetName = "sheet";

        private HeaderRow[] headerRow;

        private List<WriteOrder> writeOrderKeys;
        private int[]            width;
        private List<?>          content;

        /**
         * 如果不设置单元格的位置，全部默认为【左对齐】
         */
        private ExcelPosition[] positions;


        public ExportConfigBuilder writeOrderKeysOneByOne(String writeKey, Map<Object, Object> valueMapping) {
            if (null == writeOrderKeys) {
                this.writeOrderKeys = new ArrayList<>();
            }
            this.writeOrderKeys.add(
                    new WriteOrder()
                            .name(writeKey)
                            .valueMapping(valueMapping)
            );
            return this;
        }

        public ExportConfigBuilder writeOrderKeys(List<String> writeOrderKeys) {
            if (null == writeOrderKeys) {
                this.writeOrderKeys = new ArrayList<>();
                return this;
            }
            for (String order : writeOrderKeys) {
                this.writeOrderKeys.add(new WriteOrder().name(order));
            }
            return this;
        }

        public ExportConfigBuilder headerRow(HeaderRow... headerRow) {
            this.headerRow = headerRow;
            return this;
        }


        public ExcelExportConfig build() {
            int columnNum = writeOrderKeys == null ? 0 : writeOrderKeys.size();
            if (null == positions && columnNum > 0) {
                positions = new ExcelPosition[writeOrderKeys.size()];
                for (int i = 0; i < writeOrderKeys.size(); i++) {
                    positions[i] = ExcelPosition.LEFT;
                }
            }
            // Assert.notNull(headerRow, "excel的表头不能为空！");
            WriteOrder[] writeOrders = null;
            if (null != writeOrderKeys) {
                writeOrders = writeOrderKeys.toArray(new WriteOrder[Math.max(writeOrderKeys.size(), 0)]);
            } else {
                writeOrders = new WriteOrder[0];
            }
            return new ExcelExportConfig(handlerSort, excelType, excelName, sheetName, headerRow, width, columnNum, writeOrders, content, positions);
        }

    }


}
